//
//  CGDTest.m
//  MutlThreads
//
//  Created by 赵梁 on 2018/1/8.
//  Copyright © 2018年 赵梁. All rights reserved.
//

#import "CGDTest.h"

#import "Data1.h"
@implementation CGDTest



- (void)testDispatchQueue:(MTDispatchQueueType)queueType isAsync:(BOOL)isAsync
{
    //1. 创建队列
    dispatch_queue_t queue = nil;
    switch (queueType) {
        case MTDispatchSerialQueue:
            queue = dispatch_queue_create("test.queue.serial", DISPATCH_QUEUE_SERIAL);
            break;
        case MTDispatchConcurrentQueue:
            queue = dispatch_queue_create("test.queue.serial", DISPATCH_QUEUE_CONCURRENT);
            break;
        case MTDispatchMainQueue:
            queue = dispatch_get_main_queue();
            break;
    }
    //2. 将任务加入队列
    //提交第一个block，延时5秒打印。
    
    [self dispatch_addTaskInQueue:queue isAsync:isAsync taskBlock:^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"After 5 seconds... %@",[NSThread currentThread]);
    }];
    
    //提交第二个block，也是延时5秒打印
    [self dispatch_addTaskInQueue:queue isAsync:isAsync taskBlock:^{
        [NSThread sleepForTimeInterval:5];
        NSLog(@"After 5 seconds again... %@",[NSThread currentThread]);
    }];
    
    //延时一秒
    NSLog(@"sleep 1 second...");
    [NSThread sleepForTimeInterval:1];
    
    //挂起队列
    NSLog(@"suspend...");
    dispatch_suspend(queue);
    
    //延时10秒
    NSLog(@"sleep 2 second...");
    [NSThread sleepForTimeInterval:2];
    
    //恢复队列
    NSLog(@"resume...");
    dispatch_resume(queue);
}

- (void)dispatch_addTaskInQueue:(dispatch_queue_t)queue isAsync:(BOOL)isAsync taskBlock:(dispatch_block_t)taskBlock
{
    if (isAsync) {
        dispatch_async(queue, taskBlock);
    }
    else {
        dispatch_sync(queue, taskBlock);
    }
}

#pragma mark - dispatch_set_context/dispatch_get_context/dispatch_set_finalizer_f
//定义context，即一个结构体
typedef struct _Data {
    int number;
} Data;

//定义队列的finalizer函数，用于释放context内存
void cleanStaff(void *context) {
    NSLog(@"In clean, context number: %d", ((Data *)context)->number);
    //释放，如果是new出来的对象，就要用delete
    free(context);
}

- (void)runTest {
    //创建队列
    dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);
    
    //创建Data类型context数据并初始化
    Data *myData = malloc(sizeof(Data));
    myData->number = 10;
    
    //绑定context
    dispatch_set_context(queue, myData);
    
    //设置finalizer函数，用于在队列执行完成后释放对应context内存
    dispatch_set_finalizer_f(queue, cleanStaff);
    
    dispatch_async(queue, ^{
        //获取队列的context数据
        Data *data = dispatch_get_context(queue);
        //打印
        NSLog(@"1: context number: %d", data->number);
        //修改context保存的数据
        data->number = 20;
    });
}

#pragma mark- __bridge转换context的控制权给ARC
//定义队列的finalizer函数，用于释放context内存
void cleanStaff1(void *context) {
    //这里用__bridge转换，不改变内存管理权
    Data1 *data = (__bridge Data1 *)(context);
    NSLog(@"In clean, context number: %d", data.number);
    
    //释放context的内存！
    CFRelease(context);
}

- (void)testBody {
    //创建队列
    dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);
    
    //创建Data类型context数据并初始化
    Data1 *myData = [Data1 new];
    myData.number = 10;
    
    //绑定context
    //这里用__bridge_retained转换，将context的内存管理权从ARC移除，交由我们自己手动释放！
    dispatch_set_context(queue, (__bridge_retained void *)(myData));
    
    //设置finalizer函数，用于在队列执行完成后释放对应context内存
    dispatch_set_finalizer_f(queue, cleanStaff1);
    
    dispatch_async(queue, ^{
        //获取队列的context数据
        //这里用__bridge转换，不改变内存管理权
        Data1 *data = (__bridge Data1 *)(dispatch_get_context(queue));
        //打印
        NSLog(@"1: context number: %d", data.number);
        //修改context保存的数据
        data.number = 20;
    });
}

// GCD的栅栏方法 dispatch_barrier_async
- (void)barrier
{
    dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });
    
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });
}

//GCD的快速迭代方法 dispatch_apply
- (void)apply
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    dispatch_apply(6, queue, ^(size_t index) {
        NSLog(@"%zd------%@",index, [NSThread currentThread]);
    });
}
//GCD的队列组 dispatch_group
- (void)group
{
    dispatch_group_t group =  dispatch_group_create();
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行1个耗时的异步操作
        [NSThread sleepForTimeInterval:5];
        NSLog(@"1 执行完了");
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行1个耗时的异步操作
        [NSThread sleepForTimeInterval:4];
        NSLog(@"2 执行完了");
    });
    
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 执行1个耗时的异步操作
        [NSThread sleepForTimeInterval:3];
        NSLog(@"3 执行完了");
    });
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 等前面的异步操作都执行完毕后，回到主线程...
        NSLog(@"都执行完了");
    });
    
    //思考， 3个线程，等待他们都执行完。用dispatch_group_notify
}

@end
